package com.wobito.controller.api;


import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.pagehelper.PageHelper;
import com.wobito.common.constants.BaseResponse;
import com.wobito.common.constants.BusinessException;
import com.wobito.common.constants.ErrorCode;
import com.wobito.common.utils.*;
import com.wobito.common.utils.uuid.IdUtils;
import com.wobito.pojo.bean.Cabinet;
import com.wobito.pojo.bean.Person;
import com.wobito.pojo.dto.api.*;
import com.wobito.pojo.dto.log.BorrowLogByBookDTO;
import com.wobito.pojo.dto.log.BorrowLogByPersonDTO;
import com.wobito.pojo.mqtt.MQTTBean;
import com.wobito.pojo.mqtt.MQTTContext;
import com.wobito.pojo.mqtt.MQTTInfo;
import com.wobito.service.*;
import com.wobito.system.aspect.OperLog;
import com.wobito.system.mqtt.MQTTServer;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.List;

/**
 * @Author: lambyang
 * @CreateTime: 2024-09-24
 * @Description:
 * @Version: 1.0
 */
@RestController
@RequestMapping("/smartBookApi")
@Api(tags = "对外接口")
public class SmartBookApiController {

    @Autowired
    private ICabinetService cabinetService;
    @Autowired
    private IPersonService personService;
    @Autowired
    private IBorrowService borrowService;
    @Autowired
    private BookService bookService;
    @Autowired
    private IBorrowReturnLogService borrowReturnLogService;
    @Autowired
    private MQTTServer mqttServer;

    @GetMapping("/getCabinetOnline/{sequenceCode}")
    @ApiOperation(value = "实时获取柜子是否在线")
    @OperLog(username = "第三方调用",thing = "获取柜子是否在线")
    public BaseResponse getCabinetOnline(@PathVariable("sequenceCode") String sequenceCode) {
        String isOnline = cabinetService.selectCabinetIsOnlineByCode(sequenceCode);
        return ResultUtils.success(isOnline);
    }


    @GetMapping("/getAllCabinet")
    @ApiOperation(value = "获取所有柜子设备信息")
    @OperLog(username = "第三方调用",thing = "获取所有柜子设备信息")
    public BaseResponse getAllCabinet() {
        List<GetAllCabinetDTO> getAllCabinetDTOS = cabinetService.selectAllCabinet();
        return ResultUtils.success(getAllCabinetDTOS);
    }

    @GetMapping("/getCabinetisOnline")
    @ApiOperation(value = "获取柜子状态")
    @OperLog(username = "第三方调用", thing = "获取柜子状态")
    public BaseResponse getCabinetisOnline() {
        return ResultUtils.success();
    }

    @GetMapping("/getBookAllBorrow")
    @ApiOperation(value = "获取图书借阅情况")
    @OperLog(username = "第三方调用",thing = "获取图书借阅情况")
    public BaseResponse getBookAllBorrow(@RequestParam(value = "bookCode", required = false) Long bookCode,
                                         @RequestParam(value = "IcCode", required = false) String IcCode) {
        Long personId = null;
        Long bookId = null;
        if (IcCode != null) {
            Person person = personService.getOne(new LambdaQueryWrapper<Person>().eq(Person::getIcCode, IcCode));
            if (ObjectUtil.isNull(person)) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "借阅人不存在!");
            }
            personId = person.getId();
        }
        if (bookCode != null) {

        }
        List<GetBorrowDTO> getBorrowDTOS = borrowService.selectBorrowApi(personId, bookId);
        return ResultUtils.success(getBorrowDTOS);
    }

    @GetMapping("/getBookByBorrowReturnLog")
    @ApiOperation(value = "获取图书借阅/归还日志")
    @OperLog(username = "第三方调用",thing = "获取图书借阅/归还日志")
    public BaseResponse getBookByBorrowReturnLog(@RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
                                                 @RequestParam(value = "pageSize", defaultValue = "50") Integer pageSize,
                                                 @RequestParam(value = "bookCode", required = false) String bookCode) {
        Long bookId = null;
        if (StringUtils.isNotEmpty(bookCode)) {

        }
        PageHelper.startPage(pageNum, pageSize);
        List<BorrowLogByBookDTO> borrowLogDTOS = borrowReturnLogService.selectBookBorrowByBookId(bookId);
        return ResultUtils.success(borrowLogDTOS);
    }

    @PostMapping("/addUserInfo")
    @ApiOperation(value = "同步用户数据")
    @OperLog(username = "第三方调用",thing = "同步用户数据")
    @Transactional(rollbackFor = Exception.class)
    public BaseResponse addUserInfo(@Valid SynUserInfoVO userInfoVO) {
        if (userInfoVO.getFaceImage() == null || userInfoVO.getFaceImage().isEmpty()) {
            throw new BusinessException(ErrorCode.NULLPARAMS_ERROR, "人脸图片不能为空");
        }
        if (!ArrayUtil.contains(MimeTypeUtils.IMAGE_EXTENSION, FileTypeUtils.getFileType(userInfoVO.getFaceImage().getOriginalFilename()))) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "上传的文件类型不支持,仅可上传{bmp, gif, jpg, jpeg, png}格式");
        }
        Cabinet cabinet = cabinetService.getOne(new LambdaQueryWrapper<Cabinet>().eq(Cabinet::getSequenceCode, userInfoVO.getSequenceCode()));
        if (ObjectUtil.isNull(cabinet)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "柜子不存在!");
        }
        if (StringUtils.isEmpty(cabinet.getCameraId())) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "柜子未绑定摄像头!");
        }
        Person person1 = personService.getOne(new LambdaQueryWrapper<Person>().eq(Person::getIcCode, userInfoVO.getIcCode()));
        if (ObjectUtil.isNotNull(person1)) {
            throw new BusinessException(ErrorCode.REPEATPARAMS_ERROR, "IC卡编号已被绑定!");
        }
        //编译人脸
        String faceImage = MultipartFileToBase64Util.multipartFileToBase64(userInfoVO.getFaceImage());
        Person person = new Person(userInfoVO.getName(), userInfoVO.getIcCode(),cabinet.getId());
        MQTTBean MQTTBean = new MQTTBean("mqtt/face/" + cabinet.getCameraId(), getFaceByPerson(person, faceImage));
        //加锁，一个摄像头同一时刻只能添加一个人
        synchronized (LockUtils.getLock(LockUtils.MQTT_CAMERA_LOCK + cabinet.getCameraId())) {
            mqttServer.publish(MQTTBean);
        }
        boolean result = personService.save(person);
        if (!result) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "借阅人信息添加失败!");
        }
        return ResultUtils.successJSON("借阅人信息添加成功");
    }

    @GetMapping("/getBookByInCabinet")
    @ApiOperation(value = "获取书柜中可借阅图书")
    @OperLog(username = "第三方调用",thing = "获取书柜中可借阅图书")
    public BaseResponse getBookByInCabinet(@RequestParam(value = "sequenceCode", required = false) String sequenceCode) {
        Long cabinetId = null;
        if (StringUtils.isNotEmpty(sequenceCode)) {
            Cabinet cabinet = cabinetService.getOne(new LambdaQueryWrapper<Cabinet>().eq(Cabinet::getSequenceCode, sequenceCode));
            if (ObjectUtil.isNull(cabinet)) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "柜子不存在!");
            }
            cabinetId = cabinet.getId();
        }
        List<GetBookByCabinetDTO> bookByCabinetDTOS = bookService.selectBookByCabinet(cabinetId);
        return ResultUtils.successJSON(bookByCabinetDTOS);
    }


    @GetMapping("/getPersonBorrow")
    @ApiOperation(value = "根据用户获取个人当前借阅信息")
    @OperLog(username = "第三方调用",thing = "根据用户获取个人当前借阅信息")
    public BaseResponse getPersonBorrow(@RequestParam(value = "IcCode") String IcCode) {
        List<GetBorrowByPersonIdDTO> borrowByPersonIdDTOS = borrowService.selectBorrowByICCode(IcCode);
        return ResultUtils.successJSON(borrowByPersonIdDTOS);
    }

    @GetMapping("/getPersonBorrowReturnLog")
    @ApiOperation(value = "根据用户获取个人借阅/归还日志")
    @OperLog(username = "第三方调用",thing = "根据用户获取个人借阅/归还日志")
    public BaseResponse getPersonBorrowReturn(@RequestParam(value = "IcCode") String IcCode) {
        Person person = personService.getOne(new LambdaQueryWrapper<Person>().eq(Person::getIcCode, IcCode));
        if (ObjectUtil.isNull(person)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "借阅人不存在!");
        }
        List<BorrowLogByPersonDTO> borrowLogByPersonDTOS = borrowReturnLogService.selectBookBorrowReturnByPersonId(person.getId());
        return ResultUtils.successJSON(borrowLogByPersonDTOS);
    }

    private String getFaceByPerson(Person person, String faceImage) {
        MQTTContext mqttContext = new MQTTContext();
        mqttContext.setOperator("EditPerson");
        MQTTInfo mqttInfo = new MQTTInfo(String.valueOf(person.getId()), person.getName(), faceImage);
        mqttContext.setInfo(mqttInfo);
        mqttContext.setMessageId(IdUtils.fastSimpleUUID());
        return JSON.toJSONString(mqttContext);
    }

}
